﻿/* dollar 1.0.0 - JavaScript framework
 * (c) 2009 baboo wang <istxwang@gmail.com>
 *
 * dollar is freely distributable under the terms of an MIT-style license.
 */
var $version = '1.0.0';

var $A = function (o) {
	var ret = [];
	for (var i = 0; i < o.length; i ++) ret.push(o[i]); 
	return ret;
};

var $break = new Object();

var $continue = new Object();

var $E = function (e) {
	if ($.isString(e)) return $( '#' + e);
	if ($.isElement(e)) return new Dollar(e);	
	return e;
};

var $ = function () {
	var args = $A(arguments);
	if (args.length == 1 && $.isObject(args[0], true) && (args[0].timespan || args[0].interval) && args[0].callback) return $.Timer.add(args[0]);
	if (args.length == 0 || $.isObject(args[0], true)) {
		var _class = function () { this.__init.apply(this, arguments) };
		if (args.length) _class.prototype = args[0];
		return _class;	
	}
	if ($.isString(args[0])) {
		switch (true) {
			/*Builder Node*/
			case args[0].test(/^<(.|\n)+>$/):
 				return $.Builder.node(args[0], args[1]);	
 			
 			/*ajax*/
 			case args[0].test(/^(url|http)/i):
 				if (args[1] && args[1]['callback']) {
 					$.dataQuery(args[0].replace(/^url:/i, ''), args[1]);
 				} else {
 					new $.Ajax.Simple(args[0].replace(/^url:/i, ''), args[1]);
 				}
 				return;
 			case args[0].test(/^(get|post|json)/i): 
 				var t_method = RegExp.$1;
 				if (t_method == 'json') {
 					new $.Json(args[0].replace(/^(json):/i, ''), args[1], args[2]);	
 				} else {
 					new $.Ajax.Simple(args[0].replace(/^(get|post):/i, ''), {method:  t_method, onSuccess: args[1], postBody : args[2]});
 				}
 				return; 
 			/*Select Dom Nodes*/
 			default:
 				var es = args[0].split(';'), _es = [];
				for (var i = 0; i < es.length; i ++) {
					var ret = $.getElements(es[i].trim(), args[1]);
					if (ret === false) return false;
					_es = _es.concat(ret);	
				}
				return new Dollar(_es);	
		}	
	}
	if ($.isObject(args[0])) {
		if ($.isEvent(args[0])) {
			return args[1] in $.Event.Methods ? $.Event.Methods[args[1]](args[0], args[2], args[3]) : args[0][args[1]];
		}
		if ($.isElement(args[0]) || args[0] == document) {
			return new Dollar(args[0]);	
		}
	}
	
	if ($.isFunction(args[0])) {
		if ($.isReady) args[0]();
		if (!$.ReadyList) $.ReadyList = [];
		$.ReadyList.push(args[0]);
	}
};

$.exportTo = function () {
	var toExport = [].concat(arguments[0]);
	var targetTo = arguments[1] || $;
	//help function
	function add (o, pro) {
		var npro;
		if (/^(.+)=>(.+)$/.test(pro)) {
			pro = RegExp.$1.trim();
			npro = RegExp.$2.trim();	
		} else { npro = pro }
		if (npro in targetTo) return false;
		if ($.isFunction(o[pro])) targetTo[npro] = o[pro].bind(o);
		else targetTo[npro] = o[pro];
		return true;
	}
	
	for (var i = 0; i < toExport.length; i ++) {
		var o = toExport[i];
		if ($.isString(o)) {
			var o = $;
			toExport[i].split('.').each(function(n){o = o[n];if (!o) throw $break;});
		}
		if (!o || !o.EXPORT) continue;
		if ($.isString(o.EXPORT)) {
			if ( o.EXPORT.toLowerCase() == 'all') {
				for (var pro in o) {
					if (o.hasOwnProperty(pro) && pro !== 'EXPORT') add(o, pro);
				}
			} else {
				var pro = o.EXPORT;
				if (pro in o) add(o, pro);
			}
			continue;
		}
		if ($.isArray(o.EXPORT)) {
			for (var j = 0; j <= o.EXPORT.length; j ++) add(o, o.EXPORT[j]);
		}	
	}
};

$.grep = function (f, o, eor) {
	if ($.isString(f)) {
		f = eval ('function __temp_function(v,k){ return ' + f + '};__temp_function');
	}
	var ret = [], eor = !!eor;
	if (o.length && $.isDefined(o[0])) {
		if ($.isFunction(f)) {
			for (var i = 0; i < o.length; i++) (!!f(o[i], i) ^ eor) && ret.push(o[i]);	
		} else if (f.constructor == RegExp) {
			for (var i = 0; i < o.length; i++) (f.test(o[i]) ^ eor) && ret.push(o[i]);
		}	
	}
	return ret;
};

$.map = function (f, o) {
	if ($.isString(f)) {
		f = eval ('function __temp_function(v,k){ return ' + f + '};__temp_function');
	}
	var ret = null, r;
	if (o.length && $.isDefined(o[0])) {
		for (var i = 0; i < o.length; i++) {
			r = f (o[i], i);
			if (r && $.isDefined(r.key, r.value)) {
				if (ret == null) ret = {};
				ret[r.key] = r.value;
			} else {
				if (ret == null) ret = [];
				ret.push(r);	
			}
		}	
	} else if (o) {
		for (var pro in o) {
			if (o.hasOwnProperty(pro) && !$.isFunction(o[pro])) {
				r = f (o[pro], pro);
				if (r && $.isDefined(r.key, r.value)) {
					if (ret == null) ret = {};
					ret[r.key] = r.value;
				} else {
					if (ret == null) ret = [];
					ret.push(r);	
				}	
			}
		}	
	}
	return ret;
};

$.keys = function (o) { return $.map('k', o) };

$.values = function (o) { return $.map('v', o) };


//将对象s的属性扩展进对象d中，如果设置了noOverride，则不覆盖已存在的属性
$.extend = function (d, s, noOverride) {
	for (var p in s) {
		if (noOverride && p in d) continue;
		d[p] = s[p];	
	}
	return d;
};

//clone对象d, 如果传入了第二个参数，则对新生成的对象进行扩展
$.clone = function (d) {
	var o = new d.constructor();
	for (var pro in d) { if (d[pro] !== o[pro]) o[pro] = d[pro]; }
	return arguments[1] == undefined ? o : $.extend(o, arguments[1]);		
};

$empty = $.empty = function () {};

$.K = function (k) { return k };

$.gidbase = 0;
 
 //生成一个全局内惟一的字符串
$.gid = function () { return 'GID' + ($.gidbase++) };

$.events = ['abort', 'blur', 'change', 'click', 'dblclick', 'error', 'focus', 'keydown', 'keyup', 'load', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'reset', 'resize', 'scroll', 'select', 'submit', 'unload'];

// 判断变量是否定义
$.isDefined = function () { 
	var r = true;
	for (var i = 0; i < arguments.length; i++) if (typeof arguments[i] == 'undefined') { r = false; break; }
	return r;
};

//判断变量是否是一个数组
$.isArray = function (o) { return o && o.constructor === Array };

 //判断变量是否是一个对象，如果设置了flag为真的话，则判断该变量是一个原始类型的对象。
$.isObject = function (o, flag) { return o && (flag ? (o.constructor === Object && !$.isEvent(o) && !$.isElement(o)) : typeof o == 'object') };

 // 判断变量是否是一个字符串对象
$.isString = function (o) { return typeof o == 'string' };

//description: 判断变量是否是一个数值对象
$.isNumber = function (o) { return typeof o == 'number' };

//description: 判断变量是否是一个数值对象或字符串对象
$.isStringOrNumber = function (o) { return ['string', 'number'].include(typeof o) };

//description: 判断变量是否是一个函数
$.isFunction = function (o) { return typeof o == 'function' };

//判断变量是否是一个事件对象（注意：此方法不是完全准确）
$.isEvent = function (o) { 
	return o  && 
(String(o.constructor).indexOf('Event') != -1 || 
	(o.type && $.events.include(o.type) && typeof o.keyCode != 'undefined'));
};

// 判断变量是否是一个html element对象
$.isElement = function (o) { return o && o.nodeType === 1 && o.tagName };

//全局的错误信息存放变量 
$.error = '';

$.getElements = function () {
	var _atts = [];
	
	var _attCollect = function (a, b, c, d, e) {
		var att = e ? 'className=' + c : b;
		var i = _atts.push(att) - 1;
		return '[' + i + ']';
	};
	
	var getElementsByAttribute = function (es, attsStr) {
		var ret = [];
		atts = attsStr.split('][');
		for (var j = 0; j < atts.length; j ++) {
			var attPart = _atts[atts[j]];
			switch (true) {
				case /^[\d\s,]+$/.test(attPart): 
					var ma = attPart.split(',');
					for (var i = 0; i < ma.length; i ++) {
						var index = parseInt(ma[i]);
						if(!isNaN(index) && es.length > index) ret.push(es[index]);		
					}
					break;
				case /^:(\w+)$/.test(attPart):
					switch(RegExp.$1.toLowerCase()) {
						case 'first' : if (es.length) ret.push(es[0]); break;
						case 'last' : if (es.length) ret.push(es.last()); break;	
					}
					break; 
				case /^((?::first|\d+))\.\.((?::last|\d+)(?:\s*-\s*\d+)?)$/.test(attPart):
					var parts = attPart.split('..');
					var start = parts[0] == ':first' ? 0 : parseInt(parts[0], 10), end = parts[1].replace(/:last/, es.length - 1).trim();
					if (/^\d+$/.test(end)) {
						end = parseInt(end);	
					} else {
						//可能是一个表达式
						end = eval(end);	
					}
					for (var i = start; i <= end && i < es.length; i++) ret.push(es[i]);
					break;
				case /^(\w+)\s*(\!|\^|\$|\*)?=\s*(.+)$/.test(attPart):
					var att = RegExp.$1, etype = RegExp.$2, vl = RegExp.$3, testBool;
					for (var i = 0; i < es.length; i ++) {
						if (att == 'className') {
							testBool = es[i].className.test(new RegExp( '(^|\\s+)' + vl + '(\\s+|$)')); 
							if (testBool) ret.push(es[i]);	
						} else {
							var attVal = $.getAttribute(es[i], att), hasAtt = true;
							if (attVal === null) hasAtt = false;
							else attVal = String(attVal);
							switch (etype) {
								case '!' :
									testBool = hasAtt && (attVal != vl);
									break;
								case '^':
									testBool = hasAtt && (attVal.indexOf(vl) == 0);
									break;
								case '$':
									testBool = hasAtt && (attVal.indexOf(vl) + vl.length == attVal.length);
									break;
								case '*':
									testBool = hasAtt && (attVal.indexOf(vl) != -1);
									break;
								default:
									testBool = hasAtt && (attVal == vl);
									break;	
							}
							if (testBool) ret.push(es[i]);	
						}
					}
					break;
				case /^@(\w+)/.test(attPart):
					var attName = RegExp.$1;
					for (var i = 0; i < es.length; i ++) {
						if ($.getAttribute(es[i], attName)) ret.push(es[i]);
					}
					break;
			}
			if (j != atts.length - 1) {
				es = ret;
				ret = [];	
			}
		}
		return ret;
	};	
	return function (path) {
	var ps = path.trim().replace(/(^|\s)\./g, '$1*.').replace(/>\s+(?=\S)/g, '>').replace(/\[([^\]]+)\]/g, _attCollect).replace(/(\.)([\w-]+)/g, _attCollect).split(' '), stack1 = [], stack2 = [];
	for (var i = 0; i < ps.length; i ++) {
		if (ps[i] == '') continue;
		var p = ps[i];
		var ma =  p.match(/^([#>]?)([\w-]+|\*)(?:\[(.+)\])?$/);
		if (!ma) {
			$.error = 'wrong format:' + path;
			_atts.length = 0;
			return false;
		}
		if (stack1.length == 0) {
			if (i != 0) return [];
			stack1 = [].concat(arguments[1] || document);
		}
		switch (ma[1]) {
			case '':
				for (var j = 0; j < stack1.length; j ++) {
					var temp = $A(stack1[j].getElementsByTagName(ma[2]));
					if (temp.length) stack2.push(temp);	
				}
				break;
			case '#':
				delete stack1;
				stack1 = [];
				var e = document.getElementById(ma[2]);
				stack2 = e ? [e] : [];
				break;
			case '>':
				var tag = ma[2].toUpperCase();
				for (var j = 0; j < stack1.length; j ++) {
					var children = stack1[j].childNodes, temp = [];
					for (var k = 0; k < children.length; k ++) {
						if ($.isElement(children[k]) && (children[k].nodeName == tag || tag == '*')) {
							temp.push(children[k]);	
						}
					}
					if (temp.length) stack2.push(temp);	
				}
				break;
		}
		if (stack2.length == 0) { _atts.length = 0; return []; }
		delete stack1;
		stack1 = [];
		for (var j = 0; j < stack2.length; j ++) {
			stack1 = stack1.concat(ma[3] ? getElementsByAttribute(stack2[j], ma[3]) : stack2[j]);
		}
		delete stack2;
		stack2 = [];
	}
	_atts.length = 0;
	return stack1;	
};
} ();

$.getElementsByClassName = function (className, e) {
	$.Dom._elementsWithClass(e || document, className);	
};

$.props = $.extend({
	"for": "htmlFor",
	"class": "className",
	readonly: "readOnly",
	maxlength: "maxLength"
}, $.map(function(v){return {key:v, value:v}}, [ 
"value",  "disabled", "checked", "selected", "selectedIndex", "defaultValue", "tagName", "nodeName", "childNodes", "offsetTop", "offsetLeft",
"offsetWidth", "offsetHeight", "offsetLeft", "offsetTop", "clientWidth", "clientHeight"
]));

//获取一个Dom Element的属性
$.getAttribute = function (e, name) {
	var props = $.props;
	if (props[name]) return e[props[name]];
	if ($.Browser.IE && /src|href/.test(name.toLowerCase()))  return  e.getAttribute (name, 2);
	if (e.tagName == 'SELECT' && name == 'value') {
		return e.options[e.selectedIndex].value;	
	}
	if (e.attributes && e.attributes[name]) return e.attributes [name].nodeValue;
	return e.getAttribute ? e.getAttribute(name) : undefined;
}; 

// 设置一个Dom Element的属性
$.setAttribute = function (e, name, value) {
	var props = $.props;
	if (props[name]) { e[props[name]] = value;  return; }  
	if (e.tagName == 'SELECT' && name == 'value') {
		for (var i = 0; i < e.options.length; i ++) if (e.options[i].value == value) {e.selectedIndex = i; break;}
		return;
	}
	if (e.attributes [name]) { e.attributes[name].nodeValue = value; return;}
	e.setAttribute (name, "" + value);
};

var Dollar = $({
__init: function () { 
	this.elements = [].concat(arguments[0] || []);  
	this.e = this.elements[0]; 
	this._$ = true; 
	this.length = this.elements.length;
	for(var i = 0; i < this.elements.length; i++) this[i] = this.elements[i] ;
	//sugar
	if(this.length && this[0].tagName == 'INPUT') this.value = this[0].value;
},	

$: function () {
	var args = $A(arguments), index = false, ret;
	if ($.isNumber(args[0])) index = args.shift();
	var ma = args.shift().match(/^(\$?)(\$?)(.+)$/), isMethod = !!ma[1], wantRetVal = !!ma[2], methodOrAttrName = ma[3]; 
	if (this.length == 0) return wantRetVal  ? undefined  : this;
	if (isMethod) {
		if ('_' + methodOrAttrName in $.Dom) {
			var method = '_' + methodOrAttrName;
			if (false !== index) {
				ret = $.Dom[method].apply(this, [this[index]].concat(args));	
			}  else {
				ret = [];
				for (var i = 0; i < this.length; i ++) {
					ret.push($.Dom[method].apply(this, [this[i]].concat(args)));	
				}
				ret.length ==  1 && (ret = ret[0]);
			} 
			return wantRetVal  ? ret : this;
		}
		if (false !== index) {
			if (!this[index][methodOrAttrName]) throw "Can't fiind method:" + methodOrAttrName + "!";
			ret = this[index][methodOrAttrName](args[0], args[1], args[2]);
		} else {
			 ret = [];
			for (var i = 0; i < this.length; i ++) {
				ret.push(this[i][methodOrAttrName](args[0], args[1], args[2]));
			} 
			ret.length == 1 && (ret = ret[0]);
		}  
		return wantRetVal  ? ret : this;
		
	}
	
	//set or get attribute
	if (args[0] !== undefined) {
		if (false !== index) { 
			this.length && $.setAttribute (this[index], methodOrAttrName , args[0]);
		} else {
			for (var i = 0; i < this.length; i ++) { 
				$.setAttribute (this[i], methodOrAttrName , args[0]);
			}	
		}
		return this;	
	}
	if (false !== index) {
		return this.length && $.getAttribute(this[index], methodOrAttrName);	
	} 	
	ret = [];
	for (var i = 0; i < this.length; i ++) {
		ret.push($.getAttribute(this[i], methodOrAttrName));
	}
	return this.length && ret.length == 1 ? ret[0] : ret;
},

css: function () {
	var args = $A(arguments), index = false;
	if ($.isNumber(args[0])) index = args.shift();
	if ($.isString(args[0]) && ! /:/.test(args[0])) {	//get style value
		if (index !== false) return this.length && $.Dom._style(this[index], args[0]);
		var ret = [];
		for (var i = 0; i < this.length; i ++) { ret.push( $.Dom._style(this[i], args[0]) ) }
		return this.length && ret.length == 1 ? ret[0] : ret;
	}
	var styles;
	if ($.isString(args[0])) { //set style by css string
		styles = {};
		var cssStr = args.shift();
		if (args.length > 0) String.prototype.format(cssStr, args); 	//maybe it is useful sometime
		cssStr = cssStr.replace(/;$/, '');
		var ts = cssStr.split(';'), i, t;
		for (i = 0; i < ts.length; i ++) {
			t = ts[i].split(':');
			styles[t[0].trim()] = t[1].trim();	
		}	
	} else if ($.isObject(args[0], true)) {
		styles = args[0];	
	} else {
		throw "invalid parameters for method: Dollar.prototype.css " + String(args);
	}
	
	if (index !== false) {
		this.length && $.Dom._style(this[index], styles);
		return this;
	}
	for (i = 0; i < this.length; i ++) {
		$.Dom._style(this[i], styles);	
	}
	return this;	
},

each: function (f) {
	try {
		for (var i = 0; i < this.length; i ++) try { f(this[i], i); } catch (e) { if (e != $continue) throw e;}
	}  catch (e) {
		if (e != $break) throw e;
	}
},

find: function () {
	return $(arguments[0], this.elements);	
},

html: function () {
	var args = $A(arguments), index = false;
	if ($.isNumber(args[0])) index = args.shift();
	if (args.length == 0) {
		var ret = [];
		if (index !== false) {
			if(this.length == 1) {
				this[0].innerHTML = index;
				return this;
			}
			return this[index].innerHTML;
		}
		for (var i = 0; i < this.length; i ++) ret.push(this[i].innerHTML);
		return this.length && ret.length == 1 ? ret[0] : ret;	
	}
	if (args.length == 1) {
		if (index !== false) {
			try {
				this.length && (this[index].innerHTML = args[0]);	
			} catch (e) {
				throw "has ";	
			}
			return this;
		}
		for (var i = 0; i < this.length; i ++) {
			this[i].innerHTML = args[0];	
		}
		return this;	
	}
	return this;
},

item: function (i) { return this[i] },

fill: function (url, sets) {
	var _t = this;
	sets = sets || {};
	if (sets.preCall) sets.preCall();
	$('url:' + url, {
		method: 'get',
		onSuccess: function (t, json) {
			if (_t.length) _t[0].innerHTML = sets.process ? sets.process(t.responseText, json) : t.responseText;
			(sets.sufCall || $.empty).bind(_t[0])();
		},
		onFailure: function () { 
			if (_t.length) _t[0].innerHTML = sets.failedText || 'Fail to Load data';
			(sets.sufCall || $.empty).bind(_t[0])();
		}	
	});	
},

add : function () { 
	var args = $A(arguments);
	for (var i = 0; i < args.length; i ++) {
		this.elements.push(args[i]);
		this[this.length] = args[i];
		this.length ++;	
	}
	this.length && (thie.e = this[0]);
	return this;
},

 unbind: function () {
	for(var i = 0; i < this.length; i ++) $.Event.stopObserving(this[i]);
},

grep: function (f) {
	return new Dollar($.grep(f, this, arguments[1]));	
},

map: function (f) {
	return $.map(f, this);	
}
});

/**
 * Function property
 */
$.extend(Function.prototype, {

	bind: function () {
		var _t = this, args = $A(arguments), o = args.shift();
		return function () {
			return _t.apply(o, args.concat($A(arguments)));	
		};
	},
	
	bindAsEventListener: function () {
		var _t = this, args = $A(arguments), o = args.shift();
		return function (event) {
			_t.apply(o, [event || window.event].concat(args).concat($A(arguments)));	
		};	
	},

	 delay: function (sec, context) {
	 	var _t = context ? this.bind(context) : this;
	 	return setTimeout (_t, sec * 1000);
	}	
});

/**
 * String prototype
 */
$.extend(String.prototype, {

	camelize: function () {
  		var list = this.split('-');
  		var pos = -1, i = 0;
  		while((pos = this.indexOf('-', pos + 1)) != -1) {
  			list[i + 1] = list[i + 1].charAt(0).toUpperCase() + list[i + 1].substring(1);
  			i ++;	
  		}
  		return list.join('');	
  	},	
  	
  	decode: function () { return decodeURIComponent(this) },
 
  	encode: function () { return encodeURIComponent(this) },
  
	format: function () { var s = this; for (var i = 0; i < arguments.length; i ++) { s = s.replace(new RegExp('\\{' + i + '\\}', 'g'), arguments[i]); } return s; },
	
	
	// 'name=baboo&sex=male&country=%E4%B8%AD%E5%9B%BD'.getQueryParams(); // return {name:'baboo', sex:'male', country:'中国'}
	getQueryParams: function () {
  		var paramStrs = this.replace(/^\??/, '').split('&');
  		var ret = {};
  		for (var i = 0; i < paramStrs.length; i ++) {
  			var parts = paramStrs[i].split('=');
  			ret[parts[0].decode()] = parts[1] ? parts[1].decode() : null;	
  		}	
  		return ret;
  	},
  	
	isEmpty: function () { return /^[\s　]*$/.test(this) },
	
	/**
	 *  简单的字符串模板处理,模板变量命名形式为 ${var_name}
	 * example:
	 *  '${name} say : ${othername} get a ${animal}'.process({name:'baboo', othername:'benny', animal:'cat'}); //'baboo say: benny get a cat'
	 */
	process: function (o, fs) { 
		fs = fs || {};
    		return this.replace(/\$\{([^\}]+)\}/g, function(a, b) {
        			b = b.trim();
        			var takens = b.split('|'), v = takens.shift().trim(), f, fun_items;
        			if (! (v in o)) v = window[b] || '';
        			else v = o[v];
        			for (var i = 0; i < takens.length; i++) {
        				fun_items = takens[i].split(':');
        				f = fun_items.shift().trim();
        				if (fs[f]) {
        					v = fs[f].apply(fs, [v].concat(fun_items));	
        				} else if (String.prototype[f]) {
        					v = String.prototype[f].apply(v, fun_items);	
        				} else {
        					//output a error info?	
        				}	
        			}
        			return v;	
		})
	},
		
	test: function (reg) { return reg.test(this) },
	
	trim: function () { return this.replace(/^[\s　]+|[\s　]+$/g, '') },
	
	 //字符串截断，一个半角字符长度为1, 全角字符长度为2；截取后缀串的长度算在截取长度内。截取反缀默认为...
	truncate: function(l, t) {
    		var _t = this;
    		l = l || 30;
    		if(_t.replace(/[^\x00-\xff]/g, 'aa').length <= l) return _t;
    		if (t === undefined) t = '...';
    		l -= t.length;
    		for (var i = 0, j = 0; i < l; ++i) {
    			if (_t.charCodeAt(i - j) > 0xff) { ++i; ++j; }	
    		}
    		if ( i != l ) { --j; i -=2; }
    		return  _t.slice(0, i - j) + t;
  	}
});

/** 
 * Array prototype
 */
$.extend(Array.prototype, {
	
	each: function (f) { 
		try {
			for (var i = 0; i < this.length; i ++) try{ f(this[i], i);  } catch(e) { if(e != $continue) throw e}
		} catch (e) {
			if (e != $break) throw e;	
		}
	},
	
	last: function () { return this[this.length - 1]; },
	
	include: function (o) { return this.indexOf(o) != -1; },
	
	indexOf: function (o) { for (var i = 0; i < this.length; i ++) if (this[i] == o) return i; return -1; },
	
	grep: function (f) { return $.grep(f, this, arguments[1]) },
	
	map: function (f) { return $.map(f, this) }
});

$.events.each(function(v){
	Dollar.prototype[v] = function (observer, anony) { 
		for (var i = 0; i < this.elements.length; i ++) {
			$.Event.observe(this.elements[i], v, anony ? observer.bind(this[i]) : observer);		
		}
		return this;	
	};
	Dollar.prototype['$' + v] = function (observer) {
		for (var i = 0; i < this.elements.length; i ++) {
			$.Event.stopObserving(this[i], v, observer);		
		}
		return this;
	}; 
});
/***********************************************************************************************************************************/

//全局的异常处理函数，默认什么也不做，可以按需要重载它
$.doException = function () {};

// window作用哉中eval脚本
$.geval = function (s) {
	try {
		if(window.execScript) window.execScript(s);
		else window.eval(s);
		return true;
	} catch(e) { 
		$.doException('$.geval', e);
		return false;
	}	
};

// eval json字符串, 异常返回false
$.jeval = function (t) {
	try {
		return eval('(' + 	t + ')');
	} catch (e) {
		$.doException('$.jeval', e);
		return false;
	} 	
};

//如果传递一个函数，则直接调用它；如果传递进一个字符串，eval它
$.run = function (o) {
	if (!o) return;
	if ($.isString(o)) return eval(o);
	if ($.isFunction(o)) return o();	
};
/**
 	Dom元素扩展方法，调用途径： 通过Dollar实例对象的$方法调用
 	例：要调用$.Dom._class (e, cn) 方法 ，$(e).$('$class', cn);  如果需要返回返回值，则$(e).$('$$class', cn)
 */
$.Dom = {
	
	// 将自己添加为一个元素的最后一个子元素
	_addTo: function (e, p) { p.appendChild(e) },
	
	/*
	 *  @cn: test if contain className cn  
	 *   -cn: remove className cn
	 *  +cn:add className cn
	 *  cn1=>cn2: replace className cn1 to cn2
	 */
	_class: function (e, cn) {
		cn = cn.replace(/^(.+?)\s*=>\s*(.+)$/, '~$1 $2');
		var ma = cn.match(/^(\W)?([\w-]+)\s*([\w-]+)?$/), ocn = e.className || '', reg1 = new RegExp('(^|\\s+)(' + ma[2] + ')($|\\s+)');
		if (!ma) return false;
		switch (ma[1]) {
			case '@' : return  reg1.test(ocn);
			case '~'  : e.className = ocn.replace(reg1, '$1' + ma[3] + '$3'); break;
			case '-' : e.className = ocn.replace(reg1, '$1$3'); break;
			case '+' : 
			default: if (! $.Dom._class(e, '@' + ma[2])) e.className = ocn + (ocn == '' ? '' : ' ') + ma[2];
		}
		return true;
	},
	
	_elementsWithClass: function (e, className) {
		var children = e.getElementsByTagName('*');
		var elements = [], reg = new RegExp("(^|\\s)" + className + "(\\s|$)");
		for (var i = 0; i < children.length; i ++) {
			var child = children[i];
			if (child.className.match(reg)) 
			elements.push(child);
		}
    		return elements;		
	},
	
	_hide: function (e) { e.style.display = 'none' },
	
	_position: function (e) {
		var x = y = 0, o = e;
		var oriDisplay = o.style.display;
		o.style.display = '';
		while (e) {
			x += e.offsetLeft || 0;
			y += e.offsetTop || 0;
			e = e.offsetParent;
		}
		o.style.display = oriDisplay;
		return [x, y];	
	},	
	
	_remove: function (e) { e.parentNode.removeChild(e); return e }, 
	
	_empty: function (e) {
		var children =  $A(e.childNodes);
		for (var i = 0; i < children.length; i ++) { 
			e.removeChild(children[i]);
		}
		e.firstChild && e.removeChild (e.firstChild );
	},
	
	_show: function (e) { e.style.display = '' },
	
	_style: function (e, style) {
		/* get style */
		if ($.isString(style)) {
			var value = e.style[style.camelize()];
    			if (!value) {
      				if (document.defaultView && document.defaultView.getComputedStyle) {
        				var css = document.defaultView.getComputedStyle(e, null);
        				value = css ? css.getPropertyValue(style) : null;
      				} else if (e.currentStyle) {
        				value = e.currentStyle[style.camelize()];
      			       }
    			}
    			if (window.opera && ['left', 'top', 'right', 'bottom'].include(style) && $.Dom._style(e, 'position') == 'static') value = 'auto';
	    		return value == 'auto' ? null : value;		
		}  	
		/*set style*/
		var o = style;
		try {
			with (e) {
				for (var pro in o) {
					if ($.isFunction(o[pro])) continue;
					style[pro.camelize()] = o[pro];	
				}	
			}
		} catch (e) {
			$.doException('$.Dom._style', e);
		}	
	},

	_opacity: function (e, value) {
		if($.isIE) {
			e.style.filter = 'alpha(opacity=' + Math.round(value * 100) + ')';	
		} else {
			e.style.opacity = value;
		}
	},

	_toggleDisplay: function(e) { $.Dom[ e.style.display == 'none' ? '_show' : '_hide' ](e);},

	_append: function(e, c) {if($.isElement(e)) e.appendChild($.isString(c) ? $(c) : c);},
	
	_prepend: function(e, c) {if($.isElement(e)) e.insertBefore($.isString(c) ? $(c) : c, e.firstChild); },
	
	_before: function(e, c) {e.parentNode.insertBefore($.isString(c) ? $(c) : c, e);},

	_after: function(e, c) {e.parentNode.insertBefore($.isString(c) ? $(c) : c, e.nextSibling);},
	
	_prev: function(e, wrapit) { 
		while (e) {
			e = e.previousSibling;
			if ($.isElement(e)) return wrapit ? new Dollar(e) : e;
		}
		return null;
	},
	
	_next: function(e, wrapit) { 
		while (e) {
			e = e.nextSibling;
			if ($.isElement(e)) return wrapit ? new Dollar(e) : e;	
		}
		return null;
	},
	
	/**
	 * @example:
	 * 	$('*.toggle').toggle('click', [function(){this.style.color='red'}, function(){this.style.color='black'}]);
	 */
	_toggle: function (e, eventType, funs) {
		if (e) {
			var toggle = new $.Toggle(funs);
			$.observe(e, eventType, function(){toggle['call'](null, e)});	
		}
	}
};

$.Dom.bind = function (pro, isOverride, hasRet) {
	if (!(pro in Dollar.prototype) || isOverride) {
		Dollar.prototype[pro] = function () {
			var args = arguments, ret;
			if (this.length) {
				ret = $.Dom['_' + pro] (this[0], args.length > 0 ? args[0] : undefined, args.length > 1 ? args[1] : undefined, args.length > 2 ? args[2] : undefined);
			}
			return hasRet ? ret : this;
		};
	}
};

$.Dom.extend = function (o, isOverride, bindSets) {
	for (var pro in o) { 
		if (!$.isFunction(o[pro])) continue;
		var npro = pro;
		if (pro.charAt(0) != '_') npro = '_' + pro;
		if (! (npro in $.Dom) || isOverride) $.Dom[npro] = o[pro];
		if ($.isArray(bindSets)) $.Dom.bind(pro, bindSets[0], bindSets[1]);
	}	
};

$.$ = function (o, hasRet) {
	$.Dom.extend(o, true, [true, hasRet || false]);	
};

['empty', 'hide', 'show', 'remove', 'toggleDisplay', 'opacity', 'addTo', 'append', 'prepend', 'before', 'after', 'toggle'].each(function(pro){
	$.Dom.bind(pro);
});

['pre', 'next'].each(function(pro){
	$.Dom.bind(pro, true, true);
});

/***********************************END Dom*********************************************************/

$.Toggle = $({
	__init : function () {
		this.funs = $.isArray(arguments[0]) ? arguments[0] : $A(arguments);
		this.pos = 0;
	},

	call : function (args, obj) {
		args = [].concat(args);
		this.funs[this.pos ++ % this.funs.length].apply(obj || null, args);
	}
});

/**
 * @class $.Cookie
 */
$.Cookie = function (document, name, days, path, domain, secure) {
  	this.$document = document;
	this.$name = name;
	this.$days = days || null;
	this.$path = path || null;
	this.$domain = domain || null;
	this.$secure = secure || false;
};

/**
 * $.Cookie prototypes
 */
$.Cookie.prototype = {
	load: function () {
		var cookieval = $.Cookie.All.get(this.$document, this.$name);
		if (!cookieval) return;
		var a = cookieval.split( '&' );
		for( var i = 0; i < a.length; i ++ ) a[ i ] = a[ i ].split( ':' );
		for( var i = 0; i < a.length; i ++ ) this[ a[ i ][ 0 ] ] = a[ i ][ 1 ].decode();
		return;
	},

	remove: function () {
		$.Cookie.All.remove(this.$document, this.$name, this.$path, this.$domain);
	},

	store: function () {
		var cookieval = "";
		for (var prop in this){
			if (( prop.charAt( 0 ) == '$' ) || (( typeof this[ prop ] ) == 'function' )) continue;
			if ( cookieval != "" ) cookieval += '&';
			cookieval += prop + ':' + this[prop].encode();
		}
		$.Cookie.All.set(this.$document, this.$name, cookieval, this.$days, this.$path, this.$domain, this.$secure);
	}
};

/**
 * @Object $.Cookie.All
 */
$.Cookie.All = {
	
	get: function () {
		var args = [].concat($A(arguments)), d = args.shift();
		var allcookies = d.cookie.replace(/\s/g, '');
		var ret = [];
		if ( allcookies == "" ) return false;
		for (var i = 0; i < args.length; i ++) {
			var name = args[i];
			var start = allcookies.indexOf(name + '=');
			if (start == -1) {
				ret.push(null);
				continue;
			}
			start += name.length + 1;
			var end = allcookies.indexOf(';', start);
			if (end == -1) end = allcookies.length;
			ret.push(allcookies.substring(start, end));	
		}
		return ret.length == 1 ? ret[0] : ret;	
	},

	set: function (d, name, value, days, path, domain, secure) {
		var cookie = name + '=' + value;
		var expiration = days ? new Date((new Date()) . getTime() + days * 24 * 3600000) : null;
		if (expiration) cookie += '; expires=' + expiration.toGMTString();
		if (path) cookie += '; path=' + path;
		if (domain) cookie += ';domain=' + domain;
		if (secure) cookie += ';secure';
		d.cookie = cookie;
	},

	remove: function (d, name, path, domain) {
		var cookie = name + '=';
		if( path ) cookie += '; path=' + path;
		if( domain ) cookie += '; domain=' + domain;
		cookie += '; expires=Fri, 02-Jan-1970 00:00:00 GMT';
		d.cookie = cookie;
	}	
};
/***********************************END Cookie*******************************************************/

$.Builder = {
	EXPORT : ['node'],
	NODEMAP: { AREA: 'map',
    		CAPTION: 'table',
    		COL: 'table',
    		COLGROUP: 'table',
    		LEGEND: 'fieldset',
    		OPTGROUP: 'select',
    		OPTION: 'select',
    		PARAM: 'object',
    		TBODY: 'table',
    		TD: 'table',
    		TFOOT: 'table',
    		TH: 'table',
    		THEAD: 'table',
    		TR: 'table'
  	},
  	/**
	 * @example:
	 *	$.Builder.node('table'); 	//table element
	 *	$.Builder.node('<div style="color:red">hello,world</div>');	//div element
	 */
  	node: function (html, wrapit) {
  		if (/^\w+$/.test(html)) {
  			var e = document.createElement(html);
  			return e && wrapit ? new Dollar(e) : e;
  		}
  		if (!/^<[^>]+?\/?>((.|\n)*<\/[^>]+>)?$/.test(html)) return null;
  		var tagName = html.match(/<(\w+)(?:\s|>)/)[1].toUpperCase();
  		var parentTag = this.NODEMAP[tagName] || 'DIV';
   		var parentElement = document.createElement(parentTag);
  		try {
     			parentElement.innerHTML = html;
   		} catch(e) {}
   		var element = parentElement.firstChild || null;
   		if(element && (element.tagName != tagName)) {
     			element = element.getElementsByTagName(tagName)[0];
     		}
		if(!element) return null;
		if (arguments[1]) {
	 		this.addChildren(element, arguments[1]);
		}
		return element && wrapit ? new Dollar(element) : element;
  	},
  	addChildren: function (element, children) {
  		var cs = [].concat(children);
  		for (var i = 0; i < cs.length; i ++) {
  			if ($.isStringOrNumber(cs[i])) {
  				element.appendChild(this.text(cs[i]));
  			} else {
  				element.appendChild(cs[i]);
  			}
  		}
  	},
  
  	text: function (str) { return document.createTextNode(str); }
};
/***********************************END Node Builder*************************************************/

/**
 * @Object $.Ajax
 */
 $.Ajax = {
 	defaultSets: {
  		method : 'post',
  		contentType : 'application/x-www-form-urlencoded',
  		accept : '*/*',
  		username : null,
  		password : null,
  		asyn: true
 	},
 	querying: {},
 	cache: {}
 };
 
 /**
  * @Object $.Ajax.Base
  */
 $.Ajax.Base = {
 	getHeader: function (name) {
		try {
			return this.http.getResponseHeader(name);
		} catch (e) {
			$.doException('$.Ajax.getHeader', e);
			return false;
		}
	},
 	getHttp: function() {
 		var trys = ['new XMLHttpRequest()', 'new ActiveXObject("Msxml2.XMLHTTP")', 'new ActiveXObject("Microsoft.XMLHTTP")'];
 		for (var i = 0; i < trys.length; i ++) {
 			try {
 				return eval(trys[i]);
 			} catch(e) {}	
 		}
 		return false;
  	}
};

/**
 * @class $.Ajax.Simple
 */
$.Ajax.Simple = $($.extend({
	__init: function (url, sets) {
		this.sets = $.clone($.Ajax.defaultSets,  sets);
		this.http = this.getHttp();
		if (!this.http) return null;
		this._run(url);
	},
	_run: function (url) {
		var t = this, s = t.sets, http = t.http;
		if (!['get', 'post'].include(s.method)) s.method = 'post';
		http.open(s.method, url, s.asyn, s.username, s.password);
		http.onreadystatechange = t.onStateChange.bind(t);
		http.setRequestHeader("Accept", s.accept);
		
		if (s.postBody) {
			http.setRequestHeader("Content-type", s.contentType);
		}
		if (s.headers) {
			for (var i = 0; i < s.headers.length; i++) {
				var header = s.headers[i];
				http.setRequestHeader(header[0], header[1]);	
			}	
		}
		if (t.beforeSend) t.beforeSend(http);
		http.send(s.method == 'post' ? (s.postBody || "_") : null);
	},
	onStateChange: function () {
		var http = this.http;
    		if (http.readyState == 4) {
    			if (http.status == 200) {
    				(this.sets['onSuccess'] || $.empty)(http, this.getHeader('X-JSON'));
    			} else {
    				(this.sets['onFailure'] || $.empty)(http);
    			}	
    		}
  	}
}, $.Ajax.Base));

/**
 * @class $.Json
 * @description: 用于与服务器进行JSON数据交互，运用于数据驱动应用及解决Ajax跨域问题
 */
$.Json = $({
	__init: function(url, callback) {
		var callbackfun = false;
		if ($.isString(callback)) {
			callbackfun = callback;
		} else if ($.isFunction(callback)) {
			var gid = $.gid();
			window[gid] = function(json) { 
				callback(json); 
				window[gid] = undefined;
				try { delete window[gid] } catch (e) {} 
				if (head) setTimeout(function(){head.removeChild(script)}, 10);
			}; 
			callbackfun = gid;
		} 
		if (callbackfun) url = url + (url.indexOf('?') == -1 ? '?' : '&') + 'callback=' + callbackfun;
		var head = document.getElementsByTagName('head') [0];
		var script = document.createElement('script');
		script.src = url;
		head.appendChild(script);			
	}	
});

/**
  * @function
  * @description: 具有缓存性质的Ajax数据请求
  * 
  */
$.dataQuery = function (url, sets) {
	if (!sets) sets = {};
	var cacheID = sets.cacheID === undefined ? url : sets.cacheID;
	if ($.Ajax.cache[cacheID]) return (sets['callback'] || $.empty)($.Ajax.cache[cacheID]);
	if ($.Ajax.querying[cacheID]) return;
	$.Ajax.querying[cacheID] = true;
	new $.Ajax.Simple(url, {
		method: sets.method || 'get',
		onSuccess: function (t) {
			var data = sets['process'] ? sets['process'](t) : t.responseText;
			if (!sets.noCache) $.Ajax.cache[cacheID] = data;
			delete $.Ajax.querying[cacheID];
			(sets['callback'] || $.empty)(data);
		}, onFailure: function () { delete $.Ajax.querying[cacheID];(sets['onerror'] || $.empty)() }
	});
};
/***********************************END Ajax*********************************************************/


/**
 * @Object $.Event
 */
$.Event = {
	EXPORT: ['observe', 'stopObserving', 'Keys'],

	Keys : {BACKSPACE: 8, TAB: 9, RETURN: 13, ESC: 27, LEFT: 37, UP: 38, RIGHT: 39,DOWN: 40, DELETE: 46, HOME: 36, END: 35, PAGEUP: 33, PAGEDOWN: 34},
	observers : [],
	_observeAndCache: function(element, name, observer, useCapture) {
    		if (element.addEventListener) {
      			$.Event.observers.push([element, name, observer, useCapture]);
      			element.addEventListener(name, observer, useCapture);
    		} else if (element.attachEvent) {
      			$.Event.observers.push([element, name, observer, useCapture]);
      			element.attachEvent('on' + name, observer);
    		}
  	},

	observe: function(element, name, observer, useCapture) {
    		useCapture = useCapture || false;
    		if (name == 'keypress' && (navigator.appVersion.match(/Konqueror|Safari|KHTML/) || element.attachEvent)) {
      			name = 'keydown';
      		}
    		this._observeAndCache(element, name, observer, useCapture);
    		return [element, name, observer, useCapture];
	},

	stopObserving: function(element, name, observer, useCapture) {
		if ($.Event.observers == null || $.Event.observers.length == 0) return;
		var obs = [];
		if (arguments.length == 1) {
			var oriObs = $.Event.observers, newObs = [], item;
			for (var i = 0; i < oriObs.length; i ++) {
				item = oriObs[i];
				if (item[0] == element) obs.push(item);			
				else newObs.push(item);	
			}
			$.Event.observers  = newObs;
		} else {
			obs.push([element, name, observer, useCapture || false]);
		}   
		for (var i = 0; i < obs.length; i ++) {
			var item = obs[i]; 
			var element = item[0], name = item[1], observer = item[2], useCapture = item[3];
			if (name == 'keypress' && (navigator.appVersion.match(/Konqueror|Safari|KHTML/) || element.detachEvent)) {
      				name = 'keydown';
      			}
    			if (element.removeEventListener) {
      				element.removeEventListener(name, observer, useCapture);
    			} else if (element.detachEvent) {
      				try {
        				element.detachEvent('on' + name, observer);
      				} catch (e) {}
    			}
		}
    	},
	unloadCache: function() {
    		if ($.Event.observers == null) return;
    		for (var i = 0; i < $.Event.observers.length; i++) {
      			$.Event.stopObserving.apply(this, $.Event.observers[i]);
      			$.Event.observers[i][0] = null;
    		}
    		$.Event.observers = null;
  	}
};
/**
 * @Object $.Event.Methods
 */
$.Event.Methods = {
	/**
	 * @function
	 * @namespace $.Event.Methods
	 */
  	element: function(event, wrapit) { var e = event.target || event.srcElement; return wrapit ? new Dollar(e) : e },
  	
  	/**
	 * @function
	 * @namespace $.Event.Methods
	 */
  	find: function (event, tagName, wrapit) { var e = event.target || event.srcElement; tagName = tagName.toUpperCase(); while (e.tagName != tagName && e.tagName != 'HTML') { e = e.parentNode; } return e.tagName == tagName ? (wrapit ? new Dollar(e) : e) : false; },
  	
  	/**
	 * @function
	 * @namespace $.Event.Methods
	 */
	x: function(event) { return event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft)); },
	
	/**
	 * @function
	 * @namespace $.Event.Methods
	 */
	y: function(event) { return event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop)); },
	
	/**
	 * @function
	 * @namespace $.Event.Methods
	 */
	keyCode: function(event) { return event.keyCode || event.which; },
	
	/**
	 * @function
	 * @namespace $.Event.Methods
	 */
	stop: function(event) { var evt = event; if (evt.preventDefault) { evt.preventDefault(); evt.stopPropagation(); } else { evt.returnValue = false; evt.cancelBubble = true; }}
};
$.Event.observe(window, 'unload', $.Event.unloadCache, false);

/**
 * @Object $.Browser
 */
$.Browser = {
	
	EXPORT: ['Gecko=>isGecko', 'IE=>isIE', 'Opera=>isOpera', 'WebKit=>isWebKit', 'Version=>BrowserVersion'],

	Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 ,

	IE: /msie/.test(navigator.userAgent.toLowerCase()),
	
	Opera: !!window.opera,
	
	WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
	
  	Version: (navigator.userAgent.match( /.+?(?:rv|it|ra|ie)[\/: ]([\d.]+)/i ) || [])[1]
};

$.Timer = {
	defaultSets: { interval: 2, callback: $.empty },
	
	add: function (sets) {
		if (!this.queen) this.queen = [];
		$.extend(sets, this.defaultSets, true);
		//兼容以前的版本
		if (sets.timespan) sets.interval = sets.timespan;
		sets.callPos = new Date().getTime() + sets.interval * 1000;
		this.queen.push(sets);	
		if (!this.timer) this.timer = setInterval(this.__loop.bind(this), 40);
		return sets;
	},
	
	remove: function (sets) {
		var nqueen = [];
		for (var i = 0; i < this.queen.length; i ++) {
			if (this.queen[i] != sets) nqueen.push(this.queen[i]);	
		}
		delete this.queen;
		this.queen = nqueen;
		if (this.queen.length == 0) {
			clearInterval(this.timer);
			this.timer = false;	
		}
	},
	__loop: function () {
		var now = new Date().getTime();
		for (var i = 0; i < this.queen.length; i ++) {
			var sets = this.queen[i];
			if (sets.callPos <= now) {
				if ('callback' in sets) {
					$.run(sets.callback);
				}
				if (sets.loop) sets.callPos = now + sets.interval * 1000;
				else this.remove(sets);
			}
		}
	}	
};

 $.Effect = {
 	effects : [],
 	/**
	 * @function
	 * @namespace $.Effect
	 */
	add : function (effect) {
		var timestamp = new Date().getTime();
    		effect.startOn  = effect.delay * 1000 + timestamp;
    		effect.finishOn = effect.startOn + effect.duration * 1000;
    		effect.currentFrame = 0;
    		effect.totalFrames = effect.fps * effect.duration;
    		effect.status = 'idle';
    		this.effects.push(effect);
    		if(!this.interval) {
    			this.interval = $.Timer.add({interval: 0.04, loop:true, callback:this.__loop.bind(this)});
    		}	
	},
	
	remove: function (effect, inner) {
		var efs = [];
    		for (var i = 0; i < this.effects.length; i ++) {
    			if (this.effects[i] != effect) { 
    				efs.push(this.effects[i]);
    			} else {
    				if (inner) {
    					effect.render(effect.to);	
						effect.status = 'finish'; 
						(effect.onFinish || $.empty) ();
					}
					(effect.onRemove || $.empty) ();
    			}
    		}
    		delete this.effects;
    		this.effects = efs;
    		if (this.effects.length == 0) {
      			$.Timer.remove(this.interval);
      			this.interval = false;
    		}	
	},

	__loop: function () {
		var timePos = new Date().getTime();
    		for (var i = 0; i < this.effects.length; i ++) {
    			var ef = this.effects[i];
    			if(timePos >= ef.finishOn) {
					ef.status = 'finish'; 
					//(ef.onFinish || $.empty) ();
        			this.remove(ef, true);
        			return;  
      			}
      			if (ef.status == 'idle') {
      				(ef.onStart || $.empty) ();
      				ef.status = 'running';	
      			}
    			var pos = (timePos - ef.startOn) / (ef.finishOn - ef.startOn);
    			var frame = Math.round(pos * ef.totalFrames);
      			if(frame > ef.currentFrame) {
      				pos = ef.transition(pos);
      				pos = ef.from + ((ef.to - ef.from) * pos);
        			ef.render(pos);
        			ef.currentFrame = frame;
      			}
    		}
	}
 };
 
 $.Effect.Transitions = {
 	
 	EXPORT: 'all',
 	
	linear: function (pos) { return pos; },	
	
	sinoidal: function (pos) { return (-Math.cos(pos * Math.PI) / 2) + 0.5; },
	
	reverse: function (pos) { return 1 - pos; },
	
	flicker: function (pos) { return ((-Math.cos(pos * Math.PI) / 4) + 0.75) + Math.random() / 4; },
	
	wobble: function (pos) { return (-Math.cos(pos * Math.PI * (9 * pos)) / 2) + 0.5; },
	
	pulse: function (pos) { return (Math.floor(pos * 10) % 2 == 0 ?  (pos * 10 - Math.floor(pos * 10)) : 1 - (pos * 10 - Math.floor(pos * 10))); }
};

$.Effect.DefaultSets = {
	transition:	$.Effect.Transitions.sinoidal,
	duration:	1.0,   // seconds
	fps:      	25.0,  // max. 25fps due to Effect.Queue implementation
  	from:       	0.0,
  	to:         	1.0,
  	delay:      	0.0
};

$.effect = function (sets) {
	return $.clone($.Effect.DefaultSets, sets);	
};

$.exportTo(['Event', 'Browser', 'Effect.Transitions', 'Builder']); 

if ($.isIE && document && document.execCommand) {try{document.execCommand("BackgroundImageCache", false, true) } catch(e){}}

/**
  *  bind document ready
  *  url : http://webreflection.blogspot.com/search?q=onContent
  */
(function(){ 
	var callback = function () {
		if ($.isReady || !$.ReadyList ) return; 
		if ($.isIE) {
			try {
				document.documentElement.doScroll("left");
			} catch( error ) {
				setTimeout( arguments.callee, 0 );
				return;
			}
		}
		$.isReady  = true;
		$.ReadyList.each(function (f) { f() });
		delete $.ReadyList ;
	};
	__onload__={
        		E:function(){window.onload=null;callback()},
        		IES:function(e){if(e.readyState==="complete")this.E()}
    	}; 
    	onload=callback; 
    	if ($.isWebKit || ($.isOpera && parseInt($.BrowserVersion) < 9))  
    		(function(){/loaded|complete/.test(document.readyState)?__onload__.E():setTimeout(arguments.callee,1)})(); 
    	else if (document.addEventListener) 
    		document .addEventListener ('DOMContentLoaded', __onload__ .E, false);
    	else if (!$.isOpera || parseInt($.BrowserVersion) >= 9)
    		document.write('<SCR'+'IPT onreadystatechange="__onload__.IES(this)" src="javascript:void(0)" defer="defer"></SCR'+'IPT>');
})();
